﻿using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;

/*Acknowledgements to Eric White for the code sample to convert XElements to XNodes and vice versa
 * http://blogs.msdn.com/ericwhite/archive/2008/12/22/convert-xelement-to-xmlnode-and-convert-xmlnode-to-xelement.aspx
 * 
 * 
 * 
 * */

namespace MockingBird.Common.Infrastructure.Helpers
{
    public static class XmlHelper
    {
        public static object Deserialize(XmlDocument xDoc, Type type, string targetNamespace)
        {
            XmlSerializer serializer;
            if (targetNamespace == null)
            {
                serializer = new XmlSerializer(type);
            }
            else
            {
                serializer = new XmlSerializer(type, targetNamespace);
            }

            XmlNodeReader xnr = new XmlNodeReader(xDoc);
            object obj = serializer.Deserialize(xnr);

            return obj;
        }

        public static XDocument SerializeToXDocument(object objectToSerialize, Type typeToSerializeInto, string targetNamespace)
        {
            XmlSerializer serializer;

            if (targetNamespace == null)
            {
                serializer = new XmlSerializer(typeToSerializeInto);
            }
            else
            {
                serializer = new XmlSerializer(typeToSerializeInto, targetNamespace);
            }

            System.IO.MemoryStream memStream = new System.IO.MemoryStream();
            XmlTextWriter xtr = new XmlTextWriter(memStream, Encoding.UTF8);
            serializer.Serialize(xtr, objectToSerialize);
            memStream.Position = 0;

            XDocument xDoc;
            using (XmlReader reader = XmlReader.Create(memStream))
            {
                xDoc = XDocument.Load(reader);

            }

            return xDoc;
        }


        public static XmlDocument SerializeToXmlDocument(object objectToSerialize, Type typeToSerializeInto, string targetNamespace)
        {
            XmlDocument xDoc = new XmlDocument();

            XmlSerializer serializer;

            if (targetNamespace == null)
            {
                serializer = new XmlSerializer(typeToSerializeInto);
            }
            else
            {
                serializer = new XmlSerializer(typeToSerializeInto, targetNamespace);
            }

            System.IO.MemoryStream memStream = new System.IO.MemoryStream();
            XmlTextWriter xtr = new XmlTextWriter(memStream, Encoding.UTF8);
            serializer.Serialize(xtr, objectToSerialize);
            memStream.Position = 0;
            xDoc.Load(memStream);

            return xDoc;
        }


        public static XmlDocument GetXmlDocFromXDoc(XDocument doc)
        {
            MemoryStream memStream = new MemoryStream();
            XmlWriter xmlWriter = XmlWriter.Create(memStream);
            doc.Save(xmlWriter);
            //Close the writer so that the stream gets saved correctly
            xmlWriter.Close();

            //rewind the stream so it can be loaded into an XmlDocument
            memStream.Position = 0;
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(memStream);
            memStream.Flush();
            memStream.Close();
            return xmlDoc;
        }


        /// <summary>
        /// Extension method that returns a XElement constructed from an Xml Document
        /// </summary>
        /// <param name="xmlDoc">XmlDocument to be converted</param>
        /// <returns>XElement</returns>
        public static XElement GetXElement(this XmlDocument xmlDoc)
        {
            XDocument xDoc = new XDocument();

            using (XmlWriter xmlWriter = xDoc.CreateWriter())

                xmlDoc.WriteTo(xmlWriter);

            return xDoc.Root;

        }


        public static XElement GetXElement(this XmlNode node)
        {

            XDocument xDoc = new XDocument();

            using (XmlWriter xmlWriter = xDoc.CreateWriter())

                node.WriteTo(xmlWriter);

            return xDoc.Root;

        }



        public static XmlNode GetXmlNode(this XElement element)
        {

            using (XmlReader xmlReader = element.CreateReader())
            {

                XmlDocument xmlDoc = new XmlDocument();

                xmlDoc.Load(xmlReader);

                return xmlDoc;

            }

        }




    }
}
